package cate.game.activity.newhero;

import cate.common.table.activity.heroup.call.HeroUpCallRow;
import cate.common.table.activity.heroup.call.HeroUpEnsureRow;
import cate.common.table.activity.heroup.call.HeroUpProgressRow;
import cate.common.table.activity.heroup.herostarup.HeroStarUpRow;
import cate.common.table.activity.heroup.sign.HeroUpSignRow;
import cate.common.table.activity.heroup.signextra.HeroUpSignExtraRow;
import cate.common.table.call.row.CallWeightRow;
import cate.common.table.d.*;
import cate.common.table.item.hero.StarGroupList;
import cate.common.table.item.hero.row.HeroBaseRow;
import cate.common.table.pay.PayItemRow;
import cate.common.util.GameResult;
import cate.common.util.XT;
import cate.common.util.random.RWList;
import cate.game.activity.base.core.RoleActivitySingle;
import cate.game.activity.commonstarup.po.CommonStarUpGiftBag;
import cate.game.activity.newhero.data.HCResultItem;
import cate.game.activity.newhero.data.HCUpItem;
import cate.game.activity.newhero.data.NewHeroSignLevel;
import cate.game.activity.newhero.msg.HCUpCallResp;
import cate.game.activity.newhero.msg.NewHeroInfoResp;
import cate.game.chat.ChatContentParam;
import cate.game.res.MixRes;
import cate.game.res.MixResAdder;
import cate.game.res.MixResItem;
import cate.game.res.RewardShow;
import cate.game.role.Role;
import cate.game.role.bag.hero.Hero;
import cate.game.train.hero.TrainHeroHandler;
import com.fasterxml.jackson.annotation.JsonIgnore;
import easy.java.dev.note.NoteField;
import easy.java.practice.errorcode.EcResult;

import java.util.*;

public class NewHeroActivity extends RoleActivitySingle {
    @NoteField("免费召唤剩余次数")
    public int freeTimes;

    @NoteField("累计抽奖次数")
    public int historyDrawTimes;

    @NoteField("次数奖励领取记录")
    public Map<Integer, Boolean> numRewardMap;

    @NoteField("礼包")
    public Map<Integer, CommonStarUpGiftBag> giftPackMap;

    @NoteField(value = "签到档位")
    public Map<Integer, NewHeroSignLevel> levels;

    @NoteField(value = "未中Up累计次数")
    public int callUpTimes;

    @NoteField(value = "累计未中五星召唤次数")
    public int callFiveTimes;

    @JsonIgnore
    @NoteField(value = "召唤map")
    public Map<Integer, HCUpItem> map;

    @JsonIgnore
    @NoteField(value = "召唤英雄中间处理结果")
    public List<HCUpItem> midResult;

    @JsonIgnore
    @NoteField(value = "献祭英雄")
    LinkedList<Hero> sacrifices;

    @JsonIgnore
    @NoteField(value = "召唤物品结果")
    MixRes midPropResult;

    @JsonIgnore
    @NoteField(value = "中间献祭英雄")
    List<Hero> sacrificedHeros;

    @NoteField("钻石抽奖已抽次数")
    public int diaTimes;

    @NoteField("签到额外奖励领取状态")
    public boolean extraGot;

    @Override
    public void initialize(Role role) {
        super.initialize(role);
        if (numRewardMap == null) {
            numRewardMap = new HashMap<>();
        }
        if (giftPackMap == null) {
            giftPackMap = new HashMap<>();
        }
        giftPackMap.values().forEach(item -> {
            item.initialize(role);
        });
        if (levels == null) {
            levels = new HashMap<>();
        }
        levels.values().forEach(levelPO -> levelPO.initialize(this));
        if (map == null) {
            map = new HashMap<>();
        }
        if (midResult == null) {
            midResult = new ArrayList<>();
        }
        if (midPropResult == null) {
            midPropResult = new MixRes();
        }
        if (sacrifices == null) {
            sacrifices = new LinkedList<>();
        }
        if (sacrificedHeros == null) {
            sacrificedHeros = new ArrayList<>();
        }
    }

    @Override
    public void onEnter() {
        super.onEnter();
        if (!enable()) {
            return;
        }
        levels.values().forEach(NewHeroSignLevel::onEnter);
    }

    @Override
    public void onRoleOpen() {

    }

    @Override
    public void onRoleEnd() {
        freeTimes = 0;
        historyDrawTimes = 0;
        numRewardMap.clear();
        giftPackMap.clear();
        map.clear();
        midResult.clear();
        midPropResult.clear();
        sacrifices.clear();
        sacrificedHeros.clear();
        levels.clear();
        callUpTimes = 0;
        callFiveTimes = 0;
        extraGot = false;
    }

    @Override
    public void initSend() {
        noticeUpdate();
    }

    @Override
    public void excelCheck() {
        if (!enable()) {
            return;
        }
        //礼包
        Map<Integer, HeroStarUpRow> allConfigs = showAllGifts();
        if (allConfigs.isEmpty()) {
            giftPackMap.clear();
            return;
        }

        giftPackMap.entrySet().removeIf(kv -> !allConfigs.containsKey(kv.getKey()));
        if (giftPackMap.isEmpty()) {
            freeTimes = showBaseRow(1).freeMax;
            showGiftMap();
        }

        //签到
        Set<Integer> levelSet = showLevelSet();
        if (levelSet == null || levelSet.isEmpty()) {
            levels.clear();
            return;
        }
        levels.entrySet().removeIf(entry -> !levelSet.contains(entry.getKey()));
        for (int level : levelSet) {
            if (!levels.containsKey(level)) {
                NewHeroSignLevel levelPO = new NewHeroSignLevel(level);
                levelPO.initialize(this);
                levels.put(level, levelPO);
            }
        }
        levels.values().forEach(NewHeroSignLevel::excelCheck);
        //次数奖励
        numRewardMap.entrySet().removeIf(entry -> role.getGame().table.heroUp.progress.get(entry.getKey()) == null);
        for (HeroUpProgressRow row : role.getGame().table.heroUp.progress.getList()) {
            if (row.groupId == showBaseRow(1).rewardGroup) {
                if (!numRewardMap.containsKey(row.id)) {
                    numRewardMap.put(row.id, false);
                }
            }
        }
    }

    /**
     * 获取所有档位配置
     */
    public Set<Integer> showLevelSet() {
        Set<Integer> levelSet = new HashSet<>();
        switch (funcId()) {
            case GDFunc.NEW_HERO:
                for (HeroUpSignRow config : role.getGame().table.heroUp.sign.getList()) {
                    if (config.configTid == configTid()) {
                        levelSet.add(config.level);
                    }
                }
                break;
            default:
                break;
        }
        return levelSet;
    }

    private Map<Integer, HeroStarUpRow> showAllGifts() {
        Map<Integer, HeroStarUpRow> retMap = new HashMap<>();
        List<HeroStarUpRow> rows = role.getGame().table.heroUp.heroStarUp.getList();
        for (HeroStarUpRow config : rows) {
            if (config.configId == configTid()) {
                retMap.put(config.id, config);
            }
        }
        return retMap;
    }

    private void showGiftMap() {
        giftPackMap.clear();
        if (!enable()) {
            return;
        }
        Map<Integer, HeroStarUpRow> chooseConfigs = showAllGifts();
        for (HeroStarUpRow config : chooseConfigs.values()) {
            CommonStarUpGiftBag pack = new CommonStarUpGiftBag(config.id, false, false, 0);
            pack.initialize(role);
            giftPackMap.put(config.id, pack);
            HeroBaseRow row = role.getGame().table.hero.base.get(config.id);
            if (row == null) {
                continue;
            }
            //已拥有满足星级条件的选定英雄
            for (Hero hero : role.getBag().hero.getList()) {
                HeroBaseRow tpl = hero.getTpl(role.getGame());
                if (tpl != null) {
                    if (row.protoId == tpl.protoId && row.star <= tpl.star) {
                        //礼包开启
                        pack.enablePack();
                    }
                }
            }
        }
    }

    public void noticeUpdate() {
        role.sendNow(new NewHeroInfoResp(this));
    }

    @Override
    public void onDaySpan(boolean silence) {
        super.onDaySpan(silence);
        if (!enable()) {
            return;
        }
        levels.values().forEach(level -> level.onDaySpan(silence));
        freeTimes = showBaseRow(1).freeMax;
        diaTimes = 0;
        noticeUpdate();
    }

    /**
     * 召唤
     * @param type
     * @return
     */
    public GameResult<NewHeroActivity> call(int type) {
        GameResult<NewHeroActivity> r = new GameResult<>();
        HeroUpCallRow row = showBaseRow(type);
        if (row == null) {
            return r.fail("活动配置不存在");
        }
        r = callCheck(row);
        if (!r.ok()) {
            return r;
        }
        //道具消耗检测
        boolean isFree = false;
        boolean isDia = false;
        if (row.callType == 1 && freeTimes > 0) {
            isFree = true;
        }
        MixRes cost = new MixRes(row.costPropId);
        if (!isFree ) {
            GameResult<MixResItem> consume = cost.consumeCheck(role);
            if (!consume.ok()) {
                if (diaTimes + row.callTimes > row.diaCallTime ) {
                    return r.fail("钻石召唤次数不足");
                }
                cost = new MixRes(row.costM1Str);
                GameResult<MixResItem> consumeDia = cost.consumeCheck(role);
                if (!consumeDia.ok()) {
                    return r.fail(consumeDia);
                }
                isDia = true;
            }
        }
        r = buildRwList();
        if (!r.ok()) {
            return r;
        }
        r = modifyRateByHeroId(row);
        if (!r.ok()) {
            return r;
        }
        r = doCall(row);
        //道具消耗
        if (r.ok()) {
            if (isFree) {
                freeTimes --;
            }
            if (!isFree ) {
                cost.consume(role);
            }
            if (isDia) {
                diaTimes += row.callTimes;
                EcResult<?> exe = new MixResAdder().setRes(row.rewardExpStr)
                        .setOperation(GDOperation.ACT_HERO_UP_CALL)
                        .setDialogReward(false)
                        .setSendMailWhenFull(true)
                        .exe(role);
            }
        }
        role.getHistory().action.newHeroCallTimes(row.callTimes);
        noticeUpdate();
        return r;
    }

    private GameResult<NewHeroActivity> modifyRateByHeroId(HeroUpCallRow row) {
        GameResult<NewHeroActivity> r = new GameResult<>();
        HCUpItem item = map.get(row.heroId);
        if (item == null) {
            return r.fail("提高概率失败");
        }
        item.weight = item.getWeight() + row.rate;
        return r.success();
    }


    private GameResult<NewHeroActivity> buildRwList() {
        GameResult<NewHeroActivity> r = new GameResult<>();
        Map<Integer, CallWeightRow> rowMap = role.getGame().table.call.weight.groupMap.get(GDHCUpCall.DEFAULT_UP_GROUP);
        if (rowMap == null) {
            return r.fail("找不到配置");
        }
        rowMap.entrySet()
                .forEach(entry -> map.putIfAbsent(entry.getValue().heroId, new HCUpItem(entry.getValue())));
        return r.success();
    }

    /**
     * 召唤条件检测
     * @param row
     * @return
     */
    private GameResult<NewHeroActivity> callCheck(HeroUpCallRow row) {
        GameResult<NewHeroActivity> r = new GameResult<>();
        if (role.getBag().hero.gridEmpty() < row.callTimes) {
            role.getGame().notice.message(role, 904043, "英雄背包空间不足，请再腾出{s0}个格子再来召唤吧", row.callTimes - role.getBag().hero.gridEmpty());
            return r.fail(String.format("英雄背包空间不足，请再腾出%s个格子再来召唤吧", row.callTimes - role.getBag().hero.gridEmpty()));
        }
        if (row.callType == 1 && freeTimes > 0) {
            return r.success();
        }
        return r;
    }

    public HeroUpEnsureRow showEnsureRow() {
        return role.getGame().table.heroUp.ensure.get(configTid());
    }

    /**
     * 随机抽卡
     * @param
     * @return
     */
    private GameResult<NewHeroActivity> doCall(HeroUpCallRow row) {
        GameResult<NewHeroActivity> r = new GameResult<>();
        for (int i = 0; i < row.callTimes; i++) {
            HCUpItem resultItem;
            HeroUpEnsureRow ensureRow  = showEnsureRow();
            if (ensureRow == null) {
                return r.fail("保底配置不存在");
            }
            if (checkUp(ensureRow.ensureUpTimes)) {
                resultItem = map.get(row.heroId);
            } else if (checkFive(ensureRow.ensureFiveTimes)) {
                resultItem = doGeneralCall(ensureRow.ensureFiveGroup);
            } else {
                StarGroupList.Item item = row.config.get();
                resultItem = doGeneralCall(item.groupId);
            }

            historyDrawTimes++;
            callFiveTimes = role.getGame().table.hero.base.get(resultItem.heroId).star == 5
                    ? 0 : callFiveTimes + 1;
            callUpTimes = resultItem.heroId == row.heroId ? 0 : callUpTimes + 1;

            midResult.add(resultItem);
        }

        if (midResult == null || midResult.isEmpty() || midResult.size() < row.callTimes) {
            return r.fail("召唤错误");
        }
        if (midResult.stream()
                .filter(result -> role.getGame().table.hero.base.get(result.heroId).star > 3)
                .count() == 0 && row.limitFiveMark) {
            HCUpItem item = doGeneralCall(row.replaceGroup);
            int num = XT.randomIndex(row.callTimes);
            midResult.remove(num);
            midResult.add(item);
        }

        limitFive(row);
        List<HCResultItem> resultHero = calResultHero();
        autoSacrifices(row);

        sendFiveNotice();
        roleAddResultsSend(resultHero);

        role.getHistory().action.heroCall(GDHeroCall.Mode.UPDATE, row.callTimes);

        map.clear();
        midResult.clear();
        midPropResult.clear();
        sacrifices.clear();
        sacrificedHeros.clear();

        return r.success();
    }

    private void autoSacrifices(HeroUpCallRow row) {
        if (role.getRes().callPO.autoResolve) {
            RewardShow show = null;
            EcResult<RewardShow> resolveRes = removeAutoResolve();
            if (resolveRes.ok()) {
                show = resolveRes.data;
            }
            if (show != null) {
                midPropResult.addList(show.tplRwd);
                sacrifices.addAll(sacrificedHeros);
            }
        }
    }

    private EcResult<RewardShow> removeAutoResolve() {
        EcResult<RewardShow> r = new EcResult<>();
        Iterator<HCUpItem> iter = midResult.iterator();
        while (iter.hasNext()) {
            HCUpItem iterNow = iter.next();
            Hero hero = new Hero(role, iterNow.heroId);
            int star = hero.getTpl(role.getGame()).star;

            if (star < 4) {
                sacrificedHeros.add(hero);
                iter.remove();
            }
        }
        if (!sacrificedHeros.isEmpty()) {
            return TrainHeroHandler.calReturn(role, sacrificedHeros, TrainHeroHandler.sacrificeOpt());
        }
        return r;
    }

    private void roleAddResultsSend(List<HCResultItem> resultHero) {
        //添加奖励
        midPropResult.add(role);
        if (!midResult.isEmpty()) {
            List<Hero> heroesAdd = new LinkedList<>();
            for (HCUpItem it : midResult) {
                heroesAdd.add(new Hero(role, it.heroId));
            }
            //献祭发过奖励所以先发掉resp的奖励再把献祭奖励添加到resp中用于显示
            if (!heroesAdd.isEmpty()) {
                if (heroesAdd.size() > role.getBag().hero.calcCapacity() - role.getBag().hero.getList().size()) {
                    MixRes item = new MixRes();
                    heroesAdd.forEach(e -> item.addItem(new MixResItem(e)));
                    item.add(role, true, GDOperation.ACT_HERO_UP_CALL);
                } else {
                    role.getBag().hero.addItems(heroesAdd, null);
                }
            }
        }

        //发消息
        HCUpCallResp resp = new HCUpCallResp(resultHero, midPropResult, sacrifices);
        role.sendNow(resp);
    }

    private void sendFiveNotice() {
        if (midResult == null || midResult.isEmpty()) {
            return;
        }
        midResult.forEach(item -> {
            int star = role.getGame().table.hero.base.get(item.heroId).star;
            if (star == GDHCUpCall.HIGHT_LIGHT_STAR_REQUIRE) {
                //如果玩家抽中五星食灵发送跑马灯
                List<ChatContentParam> params = new ArrayList<>();
                params.add(ChatContentParam.c(ChatContentParam.TYPE_STRING, role.getBase().name));
                params.add(ChatContentParam.c(ChatContentParam.TYPE_HERO_ID, item.heroId));
                role.getGame().notice.lampOnline(role, GDNotice.TextId.HERO_STAR_FIVE, params);
            }
            role.getHistory().action.heroCallStar(star);
        });
    }

    private List<HCResultItem> calResultHero() {
        List<HCResultItem> resultHero = new ArrayList<>();
        if (!midResult.isEmpty()) {
            for (HCUpItem it : midResult) {
                resultHero.add(
                        new HCResultItem(it.heroId,
                                role.getGame().table.hero.base.get(it.heroId).star >= GDHCUpCall.HIGHT_LIGHT_STAR_REQUIRE));
            }
        }
        return resultHero;
    }


    private void limitFive(HeroUpCallRow row) {
        if (!row.limitFiveMark) {
            return;
        }
        int fiveNum = row.limitFiveTimes;

        List<HCUpItem> removeList = new LinkedList<>();

        for (HCUpItem item : midResult) {
            if (item.heroId == row.heroId) {
                continue;
            }
            if (role.getGame().table.hero.base.get(item.heroId).star >= 5) {
                if (fiveNum <= 0) {
                    removeList.add(item);
                } else {
                    fiveNum--;
                }
            }
        }
        midResult.removeIf(removeList::contains);
        int num = row.callTimes - midResult.size();
        for (int i = 0; i < num; i++) {
            midResult.add(doGeneralCall(row.replaceGroup));
        }
    }

    private HCUpItem doGeneralCall(int groupId) {
        if (groupId == GDHCUpCall.DEFAULT_UP_GROUP) {
            RWList<HCUpItem> rwList = new RWList<>();
            rwList.addAndSetup(map.values());
            HCUpItem item;
            item = rwList.get();
            return item;
        } else {
            Map<Integer, CallWeightRow> list = role.getGame().table.call.weight.groupMap.get(groupId);
            RWList<CallWeightRow> rwList = new RWList<>();
            rwList.addAndSetup(list.values());
            CallWeightRow item = rwList.get();
            return new HCUpItem(item);
        }
    }

    private boolean checkFive(int ensureFiveTimes) {
        if (callFiveTimes + 1 >= ensureFiveTimes) {
            return true;
        }
        return false;
    }

    private boolean checkUp(int ensureUpTimes) {
        if (callUpTimes + 1 >= ensureUpTimes) {
            return true;
        }
        return false;
    }

    /**
     * 领取次数奖励
     * @param tid
     * @return
     */
    public GameResult<NewHeroActivity> takeTimesReward(int tid) {
        GameResult<NewHeroActivity> r = new GameResult<>();
        HeroUpCallRow baseRow = showBaseRow(1);
        if (baseRow == null) {
            return r.fail("活动配置不存在");
        }
        HeroUpProgressRow row = showRewardRow(tid);
        if (row == null || !numRewardMap.containsKey(tid)) {
            return r.fail("奖励配置不存在");
        }
        if (numRewardMap.get(tid)) {
            return r.fail("奖励已领取");
        }
        if (historyDrawTimes < row.callTimes) {
            return r.fail("抽卡次数不足");
        }
        MixRes res = new MixRes(row.rewardStr);
        EcResult<?> exe = new MixResAdder().setRes(res)
                .setOperation(GDOperation.ACT_HERO_UP_CALL_PROGRESS_REWARD)
                .setDialogReward(true)
                .setSendMailWhenFull(true)
                .exe(role);
        numRewardMap.put(tid, true);
        checkMapStatus();
        noticeUpdate();
        return r;
    }

    private HeroUpProgressRow showRewardRow(int tid) {
        return role.getGame().table.heroUp.progress.get(tid);
    }

    private HeroUpCallRow showBaseRow(int type) {
        HeroUpCallRow row = role.getGame().table.heroUp.call.getMode(configTid(), type);
        return row;
    }

    /**
     * 累计次数重置检查
     */
    private void checkMapStatus() {
        boolean check = true;
        for(boolean rewardAll : numRewardMap.values()) {
            if (!rewardAll) {
                check = false;
            }
        }
        if (check) {
            HeroUpCallRow baseRow = showBaseRow(1);
            if (baseRow == null) {
                return;
            }
            numRewardMap = new HashMap<>();
            int maxScore = 0;
            for (HeroUpProgressRow row : role.getGame().table.heroUp.progress.getList()) {
                if (row.groupId == baseRow.rewardGroup) {
                    numRewardMap.put(row.id, false);
                    maxScore = Math.max(maxScore, row.callTimes);
                }
            }
            historyDrawTimes -= maxScore;
        }
    }

    /**
     * 签到
     * @return
     */
    public GameResult<NewHeroActivity> dailySign(int itemTid) {
        GameResult<NewHeroActivity> r = new GameResult<>();
        HeroUpSignRow itemConfig = showItemConfig(itemTid);
        if (itemConfig == null) {
            return r.fail("找不到奖励");
        }
        NewHeroSignLevel levelPO = levels.get(itemConfig.level);
        if (levelPO == null) {
            return r.fail("找不到档位");
        }
        r = levelPO.signReward(itemTid);
        if (r.ok()) {
            noticeUpdate();
        }
        return r;
    }

    /**
     * 获取免费礼包
     * @param tid
     * @return
     */
    public GameResult<NewHeroActivity> getReward(int tid) {
        GameResult<NewHeroActivity> r = new GameResult<>();
        HeroStarUpRow row = showGiftRow(tid);
        if (row == null) {
            return r.fail("找不到配置");
        }
        if (giftPackMap.get(tid).got) {
            return r.fail("已领取过该奖励");
        }
        if (!giftPackMap.get(tid).available) {
            return r.fail("无领取该奖励资格");
        }
        MixRes rewardRes = new MixRes(row.freeReward);
        if (rewardRes.isEmpty()) {
            return r.fail("奖励为空");
        }
        EcResult exe = new MixResAdder().setRes(rewardRes)
                .setOperation(GDOperation.ACT_HERO_STAR_UP_GIFT)
                .setOperationSub(tid)
                .setDialogReward(true)
                .setSendMailWhenFull(true)
                .exe(role);
        giftPackMap.get(tid).isGot();
        noticeUpdate();
        return r;
    }

    private HeroStarUpRow showGiftRow(int tid) {
        HeroStarUpRow row = role.getGame().table.heroUp.heroStarUp.get(tid);
        return row;
    }

    public GameResult<Void> allowSignPay(HeroUpSignRow itemConfig) {
        GameResult<Void> r = new GameResult<>();
        NewHeroSignLevel levelPO = levels.get(itemConfig.level);
        if (levelPO == null) {
            return r.fail("找不到档位");
        }
        return levelPO.allowPay(itemConfig.id);
    }

    @Override
    public GameResult<Void> allowPay(PayItemRow pir) {
        GameResult<Void> r = new GameResult<>();
        int tid = pir.funcSubId;
        HeroUpSignRow itemConfig = showItemConfig(tid);
        if (itemConfig != null) {
            //签到
            r = allowSignPay(itemConfig);
            return r;
        } else {
            //礼包
            HeroStarUpRow config = showGiftRow(tid);
            if (config == null) {
                return r.fail("未找到活动配置");
            }
            if (!giftPackMap.containsKey(tid)) {
                return r.fail("此付费礼包未激活");
            }
            if (!giftPackMap.get(tid).available) {
                return r.fail("无购买资格");
            }

            if (config.limit != -1) {
                if (giftPackMap.get(tid).buyTimes >= config.limit) {
                    return r.fail("限购次数不足");
                }
            }
            if (config.type != GDActivity.SHOP_TYPE_PAY) {
                return r.fail("不支持此购买模式");
            }
            MixRes rewardRes = new MixRes(config.payGiftPack);
            if (rewardRes.isEmpty()) {
                return r.fail("奖励为空");
            }
        }
        return r.success();
    }

    @Override
    public void onPaySuccess(PayItemRow payItemRow) {
        HeroUpSignRow itemConfig = showItemConfig(payItemRow.funcSubId);
        if (itemConfig != null) {
            //签到
            NewHeroSignLevel levelPO = levels.get(itemConfig.level);
            if (levelPO == null) {
                return;
            }
            levelPO.provideReward(itemConfig.id);
            if (itemConfig.lampId != 0) {
                List<ChatContentParam> params = new ArrayList<>();
                params.add(ChatContentParam.c(role.getBase().name));
                role.getGame().notice.lampOnline(role, itemConfig.lampId, params);
            }
        } else {
            //礼包
            HeroStarUpRow config = showGiftRow(payItemRow.funcSubId);
            if (config == null) {
                return;
            }
            MixRes reward = new MixRes(config.payGiftPack);
            EcResult exe = new MixResAdder().setRes(reward)
                    .setOperation(GDOperation.ACT_HERO_STAR_UP_GIFT)
                    .setOperationSub(payItemRow.funcSubId)
                    .setDialogReward(true)
                    .setSendMailWhenFull(true)
                    .exe(role);
            giftPackMap.get(payItemRow.funcSubId).addBuyTimes();
        }
        noticeUpdate();
    }

    public HeroUpSignRow showItemConfig(int itemTid) {
        return role.getGame().table.heroUp.sign.get(itemTid);
    }

    public GameResult<NewHeroActivity> showSignExtraReward() {
        GameResult<NewHeroActivity> r = new GameResult<>();
        if (extraGot) {
            return r.fail("额外奖励已领取");
        }
        List<Integer> rows = role.getGame().table.heroUp.sign.showExtra(configTid());
        int getSize = 0;
        for (NewHeroSignLevel level : levels.values()) {
            for (int tid :level.gotMap.keySet()) {
                if (rows.contains(tid) && level.gotMap.get(tid)) {
                    getSize ++;
                }
            }
        }
        if (rows.size() > getSize) {
            return r.fail("礼包全部购买后可领取");
        }
        HeroUpSignExtraRow extraRow = role.getGame().table.heroUp.signExtra.showExtra(configTid());
        if (extraRow == null) {
            return r.fail("奖励未配置");
        }
        EcResult exe = new MixResAdder().setRes(extraRow.reward)
                .setOperation(GDOperation.ACT_HERO_STAR_UP_GIFT)
                .setOperationSub(extraRow.id)
                .setDialogReward(true)
                .setSendMailWhenFull(true)
                .exe(role);
        extraGot = true;
        noticeUpdate();
        return r;
    }

    public void updateAvailable(String uid) {
        if (!enable()) {
            return;
        }
        Hero item = role.getBag().hero.getItem(uid);
        if (item == null) {
            return;
        }
        HeroBaseRow tpl = item.getTpl(role.getGame());
        if (tpl == null) {
            return;
        }
        HeroStarUpRow row = role.getGame().table.heroUp.heroStarUp.showHeroRow(item.tid, configTid());
        if (row == null) {
            return;
        }
        if (row.configId != configTid()) {
            return;
        }
        tryEnablePacks(tpl);
    }

    public void tryEnablePacks(HeroBaseRow tpl) {
        for (CommonStarUpGiftBag bag : giftPackMap.values()) {
            HeroBaseRow row = role.getGame().table.hero.base.get(bag.id);
            if (row == null) {
                continue;
            }
            if (row.protoId == tpl.protoId && row.star <= tpl.star) {
                bag.enablePack();
            }
        }
        noticeUpdate();
    }
}